package com.thiswhyme.republish.rabbitmq.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.List;
import java.util.concurrent.*;

/**
 * @description: 线程池配置
 * @author: thiswhyme
 * @date: 2020/12/29
 */
public class ExecutorConfig {

    public static final Logger log = LoggerFactory.getLogger(ExecutorConfig.class);

    /**
     * 默认线程池配置
     * @return
     */
    @Bean("republishDefaultExecutor")
    public Executor defaultExecutor() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(25);
        threadPool.setQueueCapacity(100);
        threadPool.setMaxPoolSize(50);
        threadPool.setRejectedExecutionHandler(new BlockingRunsPolicy());
        threadPool.setWaitForTasksToCompleteOnShutdown(true);
        threadPool.setAwaitTerminationSeconds(10);
        threadPool.setThreadNamePrefix("[Republish]Default-Thread-");
        threadPool.initialize();
        return threadPool;
    }

    /**
     * 自定义拒绝策略-阻塞
     */
    public static class BlockingRunsPolicy implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                log.warn("【defaultExecutor】线程池&队列已满，阻塞任务提交");
                executor.getQueue().put(r);
            } catch (InterruptedException e) {
                log.error("【defaultExecutor】线程池拒绝策略执行异常，errMsg：{}", e.getMessage());
            }
        }
    }


    /**
     * 关闭线程池
     * @param executor
     * @param executorName
     */
    public static void closeExecutor(ExecutorService executor, String executorName) {
        try {
            //新的任务不进队列
            executor.shutdown();
            //给10秒钟没有停止完强行停止;
            if(!executor.awaitTermination(10, TimeUnit.SECONDS)) {
                log.warn("线程池: {}-{}没有在10秒内关闭，强制关闭", executorName, executor);
                List<Runnable> droppedTasks = executor.shutdownNow();
                log.warn("线程池: {}-{}被强行关闭，阻塞队列中将有{}个将不会被执行.", executorName, executor, droppedTasks.size());
            }
            log.info("线程池:{}-{}已关闭...", executorName, executor);
        }  catch (InterruptedException e) {
            log.info("线程池:{}-{}打断...", executorName, executor);
        }
    }
}
